﻿using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Windows.Media;
using System.Xml.Linq;
using Xbim.Common;
using Xbim.Common.Geometry;
using Xbim.Ifc;
using Xbim.Ifc2x3.SharedBldgElements;
using Xbim.Ifc4.Interfaces;
using Xbim.Ifc4.Kernel;
using Xbim.Ifc4.ProductExtension;
using Xbim.IO.Xml.BsConf;
using Xbim.ModelGeometry.Scene;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using ListViewItem = System.Windows.Forms.ListViewItem;


namespace WinIFCView
{
    public partial class Form1 : Form
    {
        private ElementHost _elementHost;
        private IfcViewerControl _wpfControl;

        Dictionary<string, List<EntityInfo>> groupedEntities;


        IfcStore model = null;
        public Form1()
        {
            InitializeComponent();
            _wpfControl = new IfcViewerControl();
            _wpfControl.SelectionChanged += _wpfControl_SelectionChanged;

            controlHost.Child = _wpfControl;

            //entity = entity.ModelProvider.ObjectInstance;
            treeView1.AfterSelect += TreeView1_AfterSelect;

            this.PanelInfo.Visible=false;
        }




        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            var dlg = new OpenFileDialog();
            dlg.Filter = "IFC Files|*.ifc;*.ifczip;*.ifcxml|Xbim Files|*.xbim";
            dlg.FileOk += (s, args) =>
            {
                LoadXbimFile(dlg.FileName);
            };
            dlg.ShowDialog(this);
        }


        private void _wpfControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            var ent = e.AddedItems[0] as IPersistEntity;
            if (ent == null) {
                //txtEntityLabel.Text = "";

            }
            else {
                //txtEntityLabel.Text = ent.EntityLabel.ToString();


            }

        }


        public void Clear()
        {
            var currentIfcStore = _wpfControl.ModelProvider.ObjectInstance as IfcStore;
            currentIfcStore?.Dispose();
            _wpfControl.ModelProvider.ObjectInstance = null;
        }


        private void LoadXbimFile(string dlgFileName)
        {
            // TODO: should do the load on a worker thread so as not to lock the UI. 
            // See how we use BackgroundWorker in XbimXplorer

            Clear();
            treeView1.DataBindings.Clear();
            treeView1.Nodes.Clear();
             model = IfcStore.Open(dlgFileName);
            if (model.GeometryStore.IsEmpty)
            {
                // Create the geometry using the XBIM GeometryEngine
                try
                {
                    var context = new Xbim3DModelContext(model);

                    context.CreateContext();

                    // TODO: SaveAs(xbimFile); // so we don't re-process every time
                    Console.WriteLine($"Model Title: {model.ToString()}");
                    _wpfControl.ModelProvider.ObjectInstance = model;

                    treeview_load_with_spaces_classified(model);
                }
                catch (Exception geomEx)
                {
                    //Logger.LogError(0, geomEx, "Failed to create geometry for {filename}", dlgFileName);
                }
            }
            //_wpfControl.ModelProvider.ObjectInstance = model;
        }

        private void BtnLoadInfo_Click(object sender, EventArgs e)
        {



         
        }

        public void treeview_load(IfcStore model)
        {

            var buildings = model.Instances.OfType<IIfcBuilding>();


            // 创建根节点
            var rootNode = new TreeNode("Buildings");
            treeView1.Nodes.Add(rootNode);

            foreach (var building in buildings)
            {

                Console.WriteLine("Building====" + building.CompositionType.Value);
        

                Console.WriteLine("Building====" + building.Description);
                Console.WriteLine("Building====" + building.BuildingAddress);
                Console.WriteLine("Building====" + building.LongName);


                var buildingNode = new TreeNode($"Building: {building.Name}, Description: {building.Description}");
                //var buildingNode = new TreeNode(building.LongName);

                rootNode.Nodes.Add(buildingNode);

                var floors = building.IsDecomposedBy.SelectMany(x => x.RelatedObjects).OfType<IIfcBuildingStorey>();
                foreach (var floor in floors)
                {
                    //var floorNode = new TreeNode($"Floor: {floor.Name}, Elevation: {floor.Elevation} mm");

                    var floorNode = new TreeNode(floor.Name);

                    buildingNode.Nodes.Add(floorNode);

                    var spaces = floor.IsDecomposedBy.SelectMany(x => x.RelatedObjects).OfType<IIfcSpace>();

                    foreach (var space in spaces)
                    {
                        //var spaceInfo = $"Space: {space.Name}, GlobalId: {space.GlobalId}, " +
                        //                  $"LongName: {space.LongName}, Activated: {space.Activated}, " +
                        //                  $"Representation: {space.Representation.Name}, " +
                        //                  $"EntityLabel: {space.Representation.EntityLabel}, " +
                        //                  $"SchemaVersion: {space.Representation.Model.SchemaVersion}";

                        // 查找包含在此空间中的所有对象

                        //// 遍历所有包含在这个空间中的关系
                        //foreach (var relContained in space.ContainsElements)
                        //{
                        //    Console.WriteLine($"Space: {space.ContainsElements} ContainsElements:");
                        //    // 通过关系获取关联的对象
                        //    foreach (var relatedElement in relContained.RelatedElements)
                        //    {
                        //        Console.WriteLine($"\tContains element: {relatedElement.Name}");
                        //    }
                        //}
                        var spaceInfo = space.LongName;
                        TreeNode spaceNode = new TreeNode(spaceInfo);


                        floorNode.Nodes.Add(spaceNode);
                  
                        //GetContainedElements( spaceNode, (IfcSpatialElement)space, (IfcSpace)space);


                    }

                }




                foreach (var floor in floors)
                {
                    // 假设 IIfcBuildingStorey 有 SpatialElements 或 ContainsElements 属性
                    var elementsInFloor = floor.ContainsElements.SelectMany(rel => rel.RelatedElements).ToList();
                    Console.WriteLine($"Element elementsInFloor: {floor.Name}");
                    var spaces = floor.IsDecomposedBy.SelectMany(x => x.RelatedObjects).OfType<IIfcSpace>();

                    foreach (var space in spaces)
                    {


                        Console.WriteLine($"space Name: {space.LongName}");

                    }

                    // 现在 elementsInFloor 包含了该楼层下的所有构件
                    foreach (var element in elementsInFloor)
                    {
                        // 对于每个构件，你可以进一步处理或分析
                        //element.GetType;


                        Console.WriteLine($"Element ID: {element.EntityLabel}, Name: {element.Name},==type===={element.GetType().ToString()}");
                    }
                }

            }
        }


      

   

        // 辅助方法：安全获取实体的属性值
        private static object GetProperty(object obj, string propertyName)
        {
            var prop = obj.GetType().GetProperty(propertyName);
            return prop?.GetValue(obj, null);
        }





        private void BtnSave_Click(object sender, EventArgs e)
        {
            model.SaveAs("D:\\test.ifc");
        }








        /// <summary>
        /// 打印分类结果统计信息
        /// </summary>
        /// <param name="classifiedElements">已分类的构件字典</param>
        public void PrintClassificationStatistics(Dictionary<string, List<IPersistEntity>> classifiedElements)
        {
            Console.WriteLine("=== 构件分类统计 ===");
            int totalElements = 0;

            foreach (var kvp in classifiedElements.OrderBy(k => k.Key))
            {
                Console.WriteLine($"{kvp.Key}: {kvp.Value.Count} 个");
                totalElements += kvp.Value.Count;
            }

            Console.WriteLine($"总计: {totalElements} 个构件");
        }

        /// <summary>
        /// 在TreeView中显示分类的构件
        /// </summary>
        /// <param name="parentNode">父节点</param>
        /// <param name="classifiedElements">已分类的构件字典</param>
        public void DisplayClassifiedElementsInTree(TreeNode parentNode, Dictionary<string, List<IPersistEntity>> classifiedElements)
        {



            foreach (var kvp in classifiedElements.OrderBy(k => k.Key))
            {

                //Console.WriteLine("kvp.Key==="+ kvp.Key);


                var typeNode = new TreeNode($"{kvp.Key} ({kvp.Value.Count})");
                parentNode.Nodes.Add(typeNode);

                // 为每种类型添加具体的构件节点
                foreach (var element in kvp.Value)
                {
                    //var elementName = GetProperty(element, "Name")?.ToString() ?? "未命名";
                    var elementName = "";

        
                    if (element is IIfcSpace space)
                    {
                        elementName = GetProperty(element, "LongName")?.ToString() ?? "未命名";

                    }
                    else
                    {
                        elementName = GetProperty(element, "Name")?.ToString() ?? "未命名";


                    }

                    var elementNode = new TreeNode($"{elementName} [ID: {element.EntityLabel}]");
                    elementNode.Tag = element;
                    Console.WriteLine(elementName);

                    typeNode.Nodes.Add(elementNode);

                }
            }
        }







        /// <summary>
        /// 按类型分类所有构件，包括空间构件
        /// </summary>
        /// <param name="elements">IFC构件集合</param>
        /// <param name="spaces">IFC空间构件集合</param>
        /// <returns>按类型分组的构件字典</returns>
        public Dictionary<string, List<IPersistEntity>> ClassifyAllElementsWithSpaces(
            IEnumerable<IPersistEntity> elements,
            IEnumerable<IIfcSpace> spaces)
        {
            var classifiedElements = new Dictionary<string, List<IPersistEntity>>();

            // 先处理普通构件
            foreach (var element in elements)
            {
                string typeName = element.GetType().Name;

                if (!classifiedElements.ContainsKey(typeName))
                {
                    classifiedElements[typeName] = new List<IPersistEntity>();
                }

                classifiedElements[typeName].Add(element);
            }

            // 再处理空间构件
            foreach (var space in spaces)
            {
                string typeName = space.GetType().Name; // 通常是 "IfcSpace"

                if (!classifiedElements.ContainsKey(typeName))
                {
                    classifiedElements[typeName] = new List<IPersistEntity>();
                }

                classifiedElements[typeName].Add(space);
            }

            return classifiedElements;
        }

    


        public void treeview_load_with_spaces_classified(IfcStore model)
        {
            var buildings = model.Instances.OfType<IIfcBuilding>();

            // 创建根节点
            var rootNode = new TreeNode("Buildings");
            treeView1.Nodes.Add(rootNode);

            foreach (var building in buildings)
            {
                var buildingNode = new TreeNode($"Building: {building.Name}, Description: {building.Description}");
                rootNode.Nodes.Add(buildingNode);

                var floors = building.IsDecomposedBy.SelectMany(x => x.RelatedObjects).OfType<IIfcBuildingStorey>();
                foreach (var floor in floors)
                {
                    var floorNode = new TreeNode(floor.Name);
                    buildingNode.Nodes.Add(floorNode);

                    // 获取楼层中的构件
                    var elementsInFloor = floor.ContainsElements.SelectMany(rel => rel.RelatedElements).ToList();

                    // 获取楼层中的空间
                    var spaces = floor.IsDecomposedBy.SelectMany(x => x.RelatedObjects).OfType<IIfcSpace>();

                    // 将所有构件（包括空间）按类型分类
                    var classifiedElements = ClassifyAllElementsWithSpaces(elementsInFloor, spaces);

                    // 在TreeView中显示分类结果
                    DisplayClassifiedElementsInTree(floorNode, classifiedElements);
                }
            }
        }

        // 在Form1类中添加属性分类字典
        private Dictionary<string, List<PropertyInfo>> propertyCategories;

        // 添加节点选择事件处理函数
        private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {

            this.PanelInfo.Visible = true;
            if (e.Node.Tag is IPersistEntity entity)
            {
                //DisplayEntityProperties(entity);
                // 初始化属性分类
                InitializePropertyCategories(entity);
                UpdatePropertyCategoryCombo();
                // 显示第一个分类的属性
                if (cmbPropertyCategories.Items.Count > 0 && propertyCategories.Any())
                {
                    DisplayEntityPropertiesByCategory(entity, propertyCategories.First().Key);
                }
            }
        }




        // 显示实体属性的方法
        private void DisplayEntityProperties(IPersistEntity entity)
        {
            lvInfo.Items.Clear();

            // 设置ListView为详细信息视图
            lvInfo.View = View.Details;

            // 如果还没有列，则添加列
            if (lvInfo.Columns.Count == 0)
            {
                lvInfo.Columns.Add("属性名", 150);
                lvInfo.Columns.Add("属性值", 250);
            }

            // 使用反射获取实体的所有属性
            var properties = entity.GetType().GetProperties();
            foreach (var prop in properties)
            {
                try
                {
                    var value = prop.GetValue(entity);
                    string valueString = value?.ToString() ?? "null";

                    // 创建ListViewItem并添加到ListView中
                    var item = new ListViewItem(prop.Name);
                    item.SubItems.Add(valueString);
                    lvInfo.Items.Add(item);
                }
                catch (Exception ex)
                {
                    var item = new ListViewItem(prop.Name);
                    item.SubItems.Add($"[Error accessing value - {ex.Message}]");
                    lvInfo.Items.Add(item);
                }
            }
        }

        // 初始化属性分类
        private void InitializePropertyCategories(IPersistEntity entity)
        {
            propertyCategories = new Dictionary<string, List<PropertyInfo>>();

            var properties = entity.GetType().GetProperties();

            // 基本属性分类
            propertyCategories["基本属性"] = new List<PropertyInfo>();
            propertyCategories["几何属性"] = new List<PropertyInfo>();
            propertyCategories["标识属性"] = new List<PropertyInfo>();
            propertyCategories["其他属性"] = new List<PropertyInfo>();

            foreach (var prop in properties)
            {
                string categoryName = CategorizeProperty(prop);
                if (!propertyCategories.ContainsKey(categoryName))
                {
                    propertyCategories[categoryName] = new List<PropertyInfo>();
                }
                propertyCategories[categoryName].Add(prop);
            }

            // 移除空的分类
            var emptyCategories = propertyCategories.Where(kvp => kvp.Value.Count == 0).ToList();
            foreach (var emptyCategory in emptyCategories)
            {
                propertyCategories.Remove(emptyCategory.Key);
            }
        }

        // 更新属性分类方法，添加坐标信息分类
        private string CategorizeProperty(PropertyInfo prop)
        {
            string propName = prop.Name.ToLower();

            // 坐标相关属性
            if (new[] { "position", "location", "coordinates", "placement", "axis", "refdirection" }.Contains(propName) ||
                propName.Contains("coordinate") || propName.Contains("placement"))
                return "坐标信息";

            // 基本属性
            if (new[] { "name", "description", "longname", "objecttype" }.Contains(propName))
                return "基本属性";

            // 几何属性
            if (new[] { "geometry", "representation" }.Contains(propName) ||
                propName.Contains("geometry") || propName.Contains("representation"))
                return "几何属性";

            // 标识属性
            if (new[] { "globalid", "entitylabel", "id", "guid" }.Contains(propName) ||
                propName.Contains("id") || propName.Contains("guid"))
                return "标识属性";

            // 其他属性
            return "其他属性";
        }


        // 按分类显示实体属性的方法
        private void DisplayEntityPropertiesByCategory(IPersistEntity entity, string categoryName)
        {
            lvInfo.Items.Clear();

            // 设置ListView为详细信息视图
            lvInfo.View = View.Details;

            // 如果还没有列，则添加列
            if (lvInfo.Columns.Count == 0)
            {
                lvInfo.Columns.Add("属性名", 150);
                lvInfo.Columns.Add("属性值", 250);
            }

            // 检查分类是否存在
            if (!propertyCategories.ContainsKey(categoryName))
                return;

            // 显示指定分类的属性
            foreach (var prop in propertyCategories[categoryName])
            {
                try
                {
                    var value = prop.GetValue(entity);
                    string valueString = value?.ToString() ?? "null";

                    // 创建ListViewItem并添加到ListView中
                    var item = new ListViewItem(prop.Name);
                    item.SubItems.Add(valueString);
                    lvInfo.Items.Add(item);
                }
                catch (Exception ex)
                {
                    var item = new ListViewItem(prop.Name);
                    item.SubItems.Add($"[Error accessing value - {ex.Message}]");
                    lvInfo.Items.Add(item);
                }
            }
        }



        // 添加一个ComboBox控件用于选择属性分类（假设名为cmbPropertyCategories）
        private void UpdatePropertyCategoryCombo()
        {
            cmbPropertyCategories.SelectedIndexChanged -= cmbPropertyCategories_SelectedIndexChanged;
            cmbPropertyCategories.Items.Clear();

            if (propertyCategories != null)
            {
                foreach (var category in propertyCategories.Keys)
                {
                    cmbPropertyCategories.Items.Add(category);
                }
            }

            if (cmbPropertyCategories.Items.Count > 0)
            {
                cmbPropertyCategories.SelectedIndex = 0;
            }

            cmbPropertyCategories.SelectedIndexChanged += cmbPropertyCategories_SelectedIndexChanged;
        }

        // ComboBox选择变化事件处理
        private void cmbPropertyCategories_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbPropertyCategories.SelectedItem != null &&
                treeView1.SelectedNode?.Tag is IPersistEntity entity)
            {
                string categoryName = cmbPropertyCategories.SelectedItem.ToString();
                DisplayEntityPropertiesByCategory(entity, categoryName);
            }
        }





    }

}
